package com.feng.financial.common.rsa;

import com.feng.financial.common.exception.ValidationException;
import org.apache.tomcat.util.codec.binary.Base64;

import javax.crypto.Cipher;
import java.nio.charset.StandardCharsets;
import java.security.*;
import java.security.interfaces.RSAPrivateKey;
import java.security.interfaces.RSAPublicKey;
import java.security.spec.PKCS8EncodedKeySpec;
import java.security.spec.X509EncodedKeySpec;
import java.util.HashMap;
import java.util.Map;

public class RsaUtil {

    public static final String PRI_KEY = "PRIVATE_KEY";
    public static final String PUB_KEY = "PUBLIC_KEY";

    private static Map<String, String> keyMap = new HashMap<String, String>();  //用于封装随机产生的公钥与私钥
    public static Map<String,String> PAIR_MAP = new HashMap<>(16);

    static {
        PAIR_MAP.put(PRI_KEY,"MIIJQwIBADANBgkqhkiG9w0BAQEFAASCCS0wggkpAgEAAoICAQDSHXbPhfc/YGlL\n" +
                "Xbn2WN8GH3nwupdXWpThftP2oNeR1MGGYu+hyDZFYjmUI7cTAzBvB8SCR34+q43X\n" +
                "6wSxZvwj/zxIJ4nJJJkiEJRaIfBMFqrp0eP4pIqkhBwfB0ecBJSIz58jOcEiEKKv\n" +
                "6fm0qlIchpbH31V2MSbOnauPKMoNhnAMBdCwPctnC3rkUYdsSTQnCr6bcqw38W24\n" +
                "a3SHpLKHVkwC022oAycfK5mSRZ1bwmo2umstWFIk5GdRiE2zHxdPIg2jNAfD/S/H\n" +
                "79AD/FULbr3YCr4ud5VgsDVRYGmybJ+sROSa2PfCLhNvKu0WU5yt617JCPM5363G\n" +
                "LGr/9/itGm90LKJsnAUVMWsQmxg61BuWM+UvBlEigC/i0aLj8Fm8Dmq/sM6h9ggj\n" +
                "vr4m/shAmDH8/bSS4n1aGs7nZDZPTiaRsoYk0ALssnUQPgzPiTF0Zr2FUlC8Ewk6\n" +
                "IzLeOaBFhSPIe9w8vLF6bJhQ/49WTZd8HxJFD04M/Tj8MwsQ+JhthAVR+P5tqJVf\n" +
                "TG9ddHlg2NXq6VVK9rPqvZh2/saWUeUHc7GV+Llb3GrKLly1TtuGJslIp8lmKm1/\n" +
                "7jTFFETnTQdHGv2ZLTvXtqhJ+0KgTaTd0aZfweGWni6kj3gEym5oHVWqadK7Bvn/\n" +
                "thnsFioMhIv4jvx+MZ4Jj2jopvLZAQIDAQABAoICADPPUByby/u0qkILOm+kOloo\n" +
                "KMlTOT4w98UioOGPh5hN/epFOxGJbNhvAAOnSt1FTAwUvj/hoR+S7cbwDJgx7Lpz\n" +
                "lUm1diRDAf+EVxBijf41GK/PMYd+CzHF4alFAkNWXcneaD8nXpgnwfXem9QQq26d\n" +
                "QVDHoSsjs43/Eu6aADiVjctpI6xRkHY4PnVOJTZuVo3J+HYcMJsazRNMa8+GrP7y\n" +
                "KIwJ1mA3Zs4o0hVfVQ3rQoV8MjFcNeUi7NcN5Rrl77lzjClSCxgotj92wrQ45D+N\n" +
                "bwJ2o66RjiPpTzxhqa51WmoAEt6b4XvgIKqoyw1WUKwR/a1Up6T9orva+Adl/cs+\n" +
                "9kTc4VnukR4cypzN8krKgx04pMuARhUdNERb58cBNMX2qxDguln6wSyWi7ClMuKD\n" +
                "y8EB44vmwzh6o9WHvDb8sTJ1ClmZAr2qUItq9uorBLdrTY45ytMV9JCf3ir9euAZ\n" +
                "v7/snHqNr0wbXqEzjKDCQWB70FCDHs8HkODijzzZzs3uKoimCX/nuzNWaagYclEr\n" +
                "k+5u0at0j0lm9SlK4j+wXk1xaauFcKncwWyKoyOgsrKn0v+tzkUqj3j6zXANT1a0\n" +
                "x0RrCZ8p789LBRLDypMBIz5OzgkSTeSreN70PmdVn8Re86dWmjFB5z5bwbupsFkD\n" +
                "T4VJBObWHZPEe6eFSrYBAoIBAQDrC+pbZWDd9pkunOs4ktSmWXiYbmc6XlCDu7yr\n" +
                "gC7zCwrzJvB3SYecnP2zzh2pNHm8lrK4MwaESyGuUoq2TxROBqTvowcfmO8FVpw1\n" +
                "Yb73+Po/VXi8btv+DwED7HX553Mlp1WA122NLh2jRrE0+eQvav5PZ89sH/oRkgGY\n" +
                "OK1XI7hyA2FnuJ20QTy/8pS31OwF2ONqgZSeTvTZkC57teBYdOtmNUs75tpi+3sE\n" +
                "GcuWGw+fhfhNowF8L8Zgg8BRMK51Pu9E/ElCIJOnlpqibbXcuStcWkOVjapB5azV\n" +
                "8Hv86s/htpwoVtK04rkqvcwZD6SYBB4v61VcXS9WiPgA/FYFAoIBAQDk2JQo1sqa\n" +
                "ZXnDTPrrqP/UUXRcENJcpvLic54JDFse1Oo1WwI84/uZXlvolrPnAqwjXV5VJhUT\n" +
                "cBP1al0Awj6pT1YaowLEv89WtzO5jNIvJa6e9pllU7sQSzpRu9fXtU/D3Fv5DEy+\n" +
                "T8D9XNS7KCJLQb0412GPKr6rRgVzBpzFQ2mV7c7Y+Chk8d5XTq1UTZ5tA7bZkONd\n" +
                "CkCQaVtEh6wMOecVOvJK0sUww9HDGyV6jXadenNRT6k610TL8ToSrUBhsyjoigWY\n" +
                "vxyZpTyj5kwX2vooDF2P1FHaCvT7eOdIFCo/zZf6fU3ExqtgRPErjO3y/E+XLMod\n" +
                "rKwPD+iFvMvNAoIBAAhT6b/HPcFfhVnjcWoVubcTIHS2JK4qvUuNkUe6SO+PipnG\n" +
                "3Wo8jrN71HlUajSeiVmnNTnVhPuW9eCJSCThdGS3U4yyCASUlJNp2CsEBZIfni40\n" +
                "RwzWGLFNssmCzUNHcgr5fMwN1fHUmnQ4gvrPh8guUEhb8ztvfpq0w52zFGEsANL5\n" +
                "T7AvGFdUoGRkoeRJhPtIDfauFKfvQDmdJCh57zLzIYwDg2Dh8wbixh8FEvOEje8m\n" +
                "/f8yMVFHGA4/XMcDpIq+6hdVoPrY0KJ1cZEjtffWD7U79X0NAeVHz/HcjWgOocLr\n" +
                "h2jeeqSyC8F57AtPRJOmQbOM8P9OxeiY/cB7MEkCggEBAIyEE81Tvgm5v19VOElV\n" +
                "dui2rz0Msy5i8IZtuZ8SsCypTbo/TIt47XdJwiN5zbNOJ8Z7QT4FaTGLQyYRDlQ1\n" +
                "8WXiqhsm9r86i6RST3diaXi7qZJAFwZpuFYT6xZewfTYhsbb2rl8fO7qZ7TquFDH\n" +
                "Hu+YyQhK78OJ2pOuJhBwAfj6IK4H3FfLYHpDLWPskm9OTbXgbvj+hy0M64IAvyLA\n" +
                "L7s+Ho8hp76b1qrPwlALriKnFCs0EfTedioEHmEfmKn5KawT502J2k/lITmShT6a\n" +
                "XSTUt3+5wAVduHiq+6whm9ndT+fnZKdRI1xtJLOzAWbdXQozNOe9f8liyi9hdEQS\n" +
                "Hg0CggEBANJs4fb8URGAU6VNs6Xcu+ZrkG1T/sYI1Edxq6i8FR1+Gk9kPAQLrjkF\n" +
                "7NbRdB9Bh+ueCNyU7TlLYAv5JwC0hsTpQVypVm9Z6IYQzfyG0TtEeDBPIlHAHGz+\n" +
                "8vGQ9+MIyYAdRARXQjwbpivty77+AHhXQ6DAHYopWcXRjkCZS2ZPUqYDWaQ1K1q9\n" +
                "m5kjQDKkvQprILqJ5OCeBeFMIf3BWo8U3VZcx1/EMvdJcO9Rx/T8r2RLKNeOTCTh\n" +
                "Jwtxbx1Xwgp2bgb9+AVZqCm7gncHlrZekm12TKoFN/aQRo7DFFPEKoX3ZeVkNhtB\n" +
                "d3gkDMXaaDvPwAkTInsCCqAISWlcj2U=");
        PAIR_MAP.put(PUB_KEY,"MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA0h12z4X3P2BpS1259ljf\n" +
                "Bh958LqXV1qU4X7T9qDXkdTBhmLvocg2RWI5lCO3EwMwbwfEgkd+PquN1+sEsWb8\n" +
                "I/88SCeJySSZIhCUWiHwTBaq6dHj+KSKpIQcHwdHnASUiM+fIznBIhCir+n5tKpS\n" +
                "HIaWx99VdjEmzp2rjyjKDYZwDAXQsD3LZwt65FGHbEk0Jwq+m3KsN/FtuGt0h6Sy\n" +
                "h1ZMAtNtqAMnHyuZkkWdW8JqNrprLVhSJORnUYhNsx8XTyINozQHw/0vx+/QA/xV\n" +
                "C2692Aq+LneVYLA1UWBpsmyfrETkmtj3wi4TbyrtFlOcreteyQjzOd+txixq//f4\n" +
                "rRpvdCyibJwFFTFrEJsYOtQbljPlLwZRIoAv4tGi4/BZvA5qv7DOofYII76+Jv7I\n" +
                "QJgx/P20kuJ9WhrO52Q2T04mkbKGJNAC7LJ1ED4Mz4kxdGa9hVJQvBMJOiMy3jmg\n" +
                "RYUjyHvcPLyxemyYUP+PVk2XfB8SRQ9ODP04/DMLEPiYbYQFUfj+baiVX0xvXXR5\n" +
                "YNjV6ulVSvaz6r2Ydv7GllHlB3Oxlfi5W9xqyi5ctU7bhibJSKfJZiptf+40xRRE\n" +
                "500HRxr9mS0717aoSftCoE2k3dGmX8Hhlp4upI94BMpuaB1VqmnSuwb5/7YZ7BYq\n" +
                "DISL+I78fjGeCY9o6Kby2QECAwEAAQ==");
    }

    public static void main(String[] args) throws Exception {
        //生成公钥和私钥
        genKeyPair(512);
        //加密字符串
        String message = "df723820";
        System.out.println("随机生成的公钥为:" + keyMap.get(PUB_KEY));
        System.out.println("随机生成的私钥为:" + keyMap.get(PRI_KEY));
        String messageEn = encrypt(message,keyMap.get(PUB_KEY));
        System.out.println(message + "\t加密后的字符串为:" + messageEn);
        String messageDe = decrypt(messageEn,keyMap.get(PRI_KEY));
        System.out.println("还原后的字符串为:" + messageDe);
    }

    /**
     * 随机生成密钥对
     * @throws NoSuchAlgorithmException
     */
    public static Map<String,String> genKeyPair(int keySize) throws NoSuchAlgorithmException {
        // KeyPairGenerator类用于生成公钥和私钥对，基于RSA算法生成对象
        KeyPairGenerator keyPairGen = KeyPairGenerator.getInstance("RSA");
        // 初始化密钥对生成器，密钥大小为96-1024位
        keyPairGen.initialize(keySize,new SecureRandom());
        // 生成一个密钥对，保存在keyPair中
        KeyPair keyPair = keyPairGen.generateKeyPair();
        RSAPrivateKey privateKey = (RSAPrivateKey) keyPair.getPrivate();   // 得到私钥
        RSAPublicKey publicKey = (RSAPublicKey) keyPair.getPublic();  // 得到公钥
        String publicKeyString = new String(Base64.encodeBase64(publicKey.getEncoded()));
        // 得到私钥字符串
        String privateKeyString = new String(Base64.encodeBase64((privateKey.getEncoded())));
        // 将公钥和私钥保存到Map
        keyMap.put(PUB_KEY,publicKeyString);  //0表示公钥
        keyMap.put(PRI_KEY,privateKeyString);  //1表示私钥
        return keyMap;
    }
    /**
     * RSA公钥加密
     *
     * @param str
     *            加密字符串
     * @param publicKey
     *            公钥
     * @return 密文
     * @throws Exception
     *             加密过程中的异常信息
     */
    public static String encrypt( String str, String publicKey ) throws ValidationException {
        String encrypt = null;
        try {
            //base64编码的公钥
            byte[] decoded = Base64.decodeBase64(publicKey);
            RSAPublicKey pubKey = (RSAPublicKey) KeyFactory.getInstance("RSA").generatePublic(new X509EncodedKeySpec(decoded));
            //RSA加密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.ENCRYPT_MODE, pubKey);
            encrypt = Base64.encodeBase64String(cipher.doFinal(str.getBytes(StandardCharsets.UTF_8)));
        } catch (Exception e) {
            throw new ValidationException(null,"加密失败");
        }
        return encrypt;
    }

    /**
     * RSA私钥解密
     *
     * @param str
     *            加密字符串
     * @param privateKey
     *            私钥
     * @return 铭文
     * @throws Exception
     *             解密过程中的异常信息
     */
    public static String decrypt(String str, String privateKey) throws ValidationException{
        String outStr = null;
        try {
            //64位解码加密后的字符串
            byte[] inputByte = Base64.decodeBase64(str.getBytes(StandardCharsets.UTF_8));
            //base64编码的私钥
            byte[] decoded = Base64.decodeBase64(privateKey);
            RSAPrivateKey priKey = (RSAPrivateKey) KeyFactory.getInstance("RSA").generatePrivate(new PKCS8EncodedKeySpec(decoded));
            //RSA解密
            Cipher cipher = Cipher.getInstance("RSA");
            cipher.init(Cipher.DECRYPT_MODE, priKey);
            outStr = new String(cipher.doFinal(inputByte));
        } catch (Exception e) {
            throw new ValidationException(null,"解密失败" +
                    "");
        }
        return outStr;
    }



}

